<template>
  <a-modal
    :width="1000"
    :height="550"
    v-model:visible="dialog"
    :title="t('计算式配置')"
    :maskClosable="false"
    @ok="submitDialog"
    @cancel="closeDialog"
    style="overflow: auto"
  >
    <a-layout class="config-container" hasSider>
      <a-layout-sider width="300">
        <div class="component-list">
          <a-collapse v-model:activeKey="activeKey" expand-icon-position="right">
            <a-collapse-panel
              v-for="(item, index) in selectedComponents"
              :key="index"
              :header="item.label"
            >
              <draggable
                v-model="item.children"
                item-key="item.key"
                :group="{ name: 'computation', pull: 'clone', put: false }"
                :sort="false"
              >
                <template #item="{ element }">
                  <a-tag
                    :color="tagColor(item, element)"
                    :class="{ 'disabled-tag': disabledCom(element.key) }"
                  >
                    {{ element.label }}
                  </a-tag>
                </template>
              </draggable>
            </a-collapse-panel>
          </a-collapse>
        </div>
      </a-layout-sider>
      <a-layout-content class="bgcWhite">
        <div class="title">{{ t('计算公式') }}</div>
        <div class="btn-list">
          <div>
            <draggable
              v-model="operatingBtnList"
              :group="{ name: 'computation', pull: 'clone', put: false }"
              item-key="item.label"
              :sort="false"
            >
              <template #item="{ element }">
                <a-tag>
                  {{ element.label }}
                </a-tag>
              </template>
            </draggable>
          </div>
          <div class="input-number">
            <span>{{ t('数字：') }}</span>
            <a-input-number v-model:value="number" />
            <a-button type="primary" @click="addNumber">{{ t('确定') }}</a-button>
          </div>
        </div>
        <div class="computational-box">
          <draggable
            v-model="computationalList"
            group="computation"
            item-key="key"
            @add="addComputationalList"
            :class="['draggable', { minHeight: !computationalList.length }]"
          >
            <template #item="{ element, index }">
              <div @mouseenter="mouseenter(index)" @mouseleave="isMouseenter = false">
                <a-select
                  v-model:value="element.computationalMethod"
                  style="width: 85px"
                  v-if="element.computationalMethod"
                >
                  <a-select-option value="sum">{{ t('总和') }}</a-select-option>
                  <a-select-option value="mean">{{ t('平均数') }}</a-select-option>
                  <a-select-option value="max">{{ t('最大值') }}</a-select-option>
                  <a-select-option value="min">{{ t('最小值') }}</a-select-option>
                </a-select>
                <a-tag color="blue" closable style="padding: 5px" @close="delTag(index)">
                  <span>{{ element.label }}</span>
                </a-tag>
              </div>
            </template>
          </draggable>
          <div v-if="!computationalList.length" class="computational-text">
            <p style="font-size: 24px; color: #606266">{{ t('拖拽左侧到此处进行添加') }}</p>
            <p>{{ t('变量之间可通过计算公式进行运算（例：销售单价 * 销售数量）') }}</p>
          </div>
        </div>
      </a-layout-content>
    </a-layout>
  </a-modal>
</template>

<script lang="ts" setup>
  import { ref, inject, reactive, onMounted } from 'vue';
  import { ComputationalConfig } from '/@/components/Designer/src/types';
  import draggable from 'vuedraggable';
  import { cloneDeep, random } from 'lodash-es';
  import { useI18n } from '/@/hooks/web/useI18n';
  const { t } = useI18n();
  const props = defineProps({
    computationalDialog: { type: Boolean },
    computationalConfig: {
      type: Array as PropType<ComputationalConfig[]>,
      default: [],
    },
  });
  const { widgetForm, widgetFormSelect } = inject('state') as any; //整个表单json配置
  const operatingBtnList = reactive([
    {
      key: 1,
      operation: '＋',
      label: '+',
      type: 'operation',
    },
    {
      key: 2,
      operation: '－',
      label: '-',
      type: 'operation',
    },
    {
      key: 3,
      operation: '×',
      label: '*',
      type: 'operation',
    },
    {
      key: 4,
      operation: '÷',
      label: '/',
      type: 'operation',
    },
    {
      key: 5,
      operation: '(',
      label: '(',
      type: 'operation',
    },
    {
      key: 6,
      operation: ')',
      label: ')',
      type: 'operation',
    },
    {
      key: 7,
      operation: '.',
      label: '.',
      type: 'operation',
    },
  ]);
  const number = ref<string>('');
  const isMouseenter = ref<Boolean>(false);
  const computationalList = ref<Array<any>>([]);
  const mouseenterIndex = ref<number>();
  const activeKey = ref([0]);
  const selectedComponents = ref<Array<any>>([]);
  const dialog = ref(props.computationalDialog);
  onMounted(() => {
    if (widgetForm.list.length) {
      getTableComponents(widgetForm.list, t('主表组件列表'));
    }
    if (props.computationalConfig.length) {
      computationalList.value = cloneDeep(props.computationalConfig);
    }
  });

  const emit = defineEmits([
    'update:computationalDialog',
    'setComputationalConfigValue',
    'update:computationalConfig',
  ]);

  const getTableComponents = (list, tableName, key?) => {
    list.forEach((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getTableComponents(child.list, tableName);
        }
      } else if (item.type === 'one-for-one') {
        getTableComponents(item.children, `${item.label}-${item.key}`, item.key);
      } else if (item.type === 'form') {
        const hasMethods = item.children.some((child) => {
          return child.key === widgetFormSelect.key;
        });
        const itemChildren = item.children.filter((child) => {
          child.computationalMethod = hasMethods ? undefined : 'sum';
          return child.type === 'computational' || child.type === 'money-chinese';
        });

        selectedComponents.value.push({
          label: `${item.label}-${item.key}`,
          key: item.key,
          children: itemChildren,
        });
      } else if (item.type === 'computational' || item.type === 'money-chinese') {
        const index = selectedComponents.value.findIndex((x) => x.label === tableName);
        if (index !== -1) {
          selectedComponents.value[index].children.push(item);
        } else {
          const tableChildren = [item];
          if (tableName === t('主表组件列表')) {
            selectedComponents.value.unshift({
              label: tableName,
              key: '1',
              children: tableChildren,
            });
          } else {
            selectedComponents.value.push({
              label: tableName,
              key: key,
              children: tableChildren,
            });
          }
        }
      }
    });
  };

  const tagColor = (tableItem, componentItem) => {
    if (widgetFormSelect.key === componentItem.key) return '#f4f4f5';
    const currentItem = tableItem.children.some((item: any) => {
      return item.key === widgetFormSelect.key;
    });
    return currentItem ? 'green' : 'blue';
  };

  const disabledCom = (currentKey) => {
    if (widgetFormSelect.key === currentKey) return true;
    const isDisabled = widgetFormSelect.options.beAdoptedComponent.some((key: string) => {
      return key === currentKey;
    });
    return isDisabled;
  };

  const setBeAdoptedComponent = (list, key) => {
    list.forEach((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          setBeAdoptedComponent(child.list, key);
        }
      } else if (item.type === 'form') {
        setBeAdoptedComponent(item.children, key);
      } else if (item.key === key) {
        if (!item.options.beAdoptedComponent.includes(widgetFormSelect.key)) {
          if (!item.options.beAdoptedComponent) item.options.beAdoptedComponent = [];
          //被引用的组件不能引用当前组件
          item.options.beAdoptedComponent.push(widgetFormSelect.key);
          if (widgetFormSelect.options?.beAdoptedComponent.length) {
            item.options.beAdoptedComponent.push(...widgetFormSelect.options?.beAdoptedComponent);
          }
        }
      }
    });
  };

  //编辑时 去掉已经删除的组件引用
  const deleteBeAdoptedComponent = (list, keys) => {
    keys.forEach((key) => {
      list.forEach((item) => {
        if (['tab', 'grid', 'card'].includes(item.type)) {
          for (const child of item.layout!) {
            deleteBeAdoptedComponent(child.list, keys);
          }
        } else if (item.type === 'form') {
          deleteBeAdoptedComponent(item.children, keys);
        } else if (item.key === key) {
          //被引用的组件不能引用当前组件
          item.options.beAdoptedComponent = item.options.beAdoptedComponent.filter(
            (x) => x !== widgetFormSelect.key,
          );
        }
      });
    });
  };
  const submitDialog = () => {
    let configValue = '';
    const computationalConfig: ComputationalConfig[] = [];
    computationalList.value.map((item: any) => {
      const text = item.computationalMethod
        ? `${item.computationalMethod}(${item.label})`
        : item.label;
      let isMainForm;
      if (item.hasOwnProperty('isMainForm')) {
        isMainForm = item.isMainForm;
      } else {
        if (item.type === 'computational' || item.type === 'money-chinese') {
          isMainForm = !(item?.isSubFormChild || item?.isSingleFormChild);
        } else {
          isMainForm = undefined;
        }
      }
      configValue = configValue.concat(text);
      computationalConfig.push({
        $index: item.$index,
        label: item.label,
        type: item.type,
        key: item.key,
        bindTable: item.bindTable,
        bindField: item.bindField,
        computationalMethod: item?.computationalMethod,
        isMainForm: isMainForm,
      });
      setBeAdoptedComponent(widgetForm.list, item.key);
    });
    const currentConfigKeys = computationalConfig.map((x) => x.bindTable && x.key);
    const oldConfigKeys = props.computationalConfig.map((x) => x.bindTable && x.key);

    // 被删除的引用组件
    const needDeleteKeys = oldConfigKeys.filter((old) => {
      return old && currentConfigKeys.indexOf(old) === -1;
    });

    deleteBeAdoptedComponent(widgetForm.list, needDeleteKeys);
    emit('setComputationalConfigValue', configValue);
    emit('update:computationalConfig', computationalConfig);
    emit('update:computationalDialog', false);
  };

  const closeDialog = () => {
    emit('update:computationalDialog', false);
  };
  const addComputationalList = (e) => {
    computationalList.value[e.newIndex] = cloneDeep(computationalList.value[e.newIndex]);
    computationalList.value[e.newIndex].$index = random(100, 999);
  };
  const addNumber = () => {
    if (number.value) {
      computationalList.value.push({ label: number.value, type: 'operation' });
    }
  };
  const mouseenter = (index: number) => {
    mouseenterIndex.value = index;
    isMouseenter.value = true;
  };
  const delTag = (index) => {
    computationalList.value.splice(index, 1);
  };
</script>

<style lang="less" scoped>
  .bgcWhite {
    background: #fff;

    .btn-list {
      display: flex;
      justify-content: space-between;
      padding: 10px;
      border-bottom: 1px solid #dcdfe6;

      :deep(.ant-tag) {
        font-size: 18px !important;
        padding: 5px 15px !important;
        margin-bottom: 10px;
        cursor: move;
      }

      .input-number {
        display: flex;
        align-items: center;

        :deep(.ant-input-number) {
          width: 100px;
          margin-right: 10px;
        }
      }
    }

    .computational-box {
      min-height: 300px;
      padding: 5px 10px;

      .draggable {
        display: flex;
        flex-wrap: wrap;
        gap: 5px;
        font-size: 13px;

        > div {
          height: 30px;
          line-height: 30px;
          margin-top: 5px;
        }

        > span:nth-of-type(1) {
          height: 30px;
          display: flex;
          align-items: center;
        }

        p:nth-child(1) {
          color: #606266;
        }

        p:nth-child(2) {
          color: #9e9d9d;
        }
      }

      .computational-text {
        text-align: center;
        margin-top: -200px;
      }
    }
  }

  .minHeight {
    min-height: 300px;
  }

  .config-container {
    margin: 10px;
    border: 1px solid #dcdfe6;

    .component-list {
      display: flex;
      flex-wrap: wrap;

      :deep(.ant-collapse) {
        width: 100%;
        border: none;
      }
    }
  }

  :deep(.ant-tag) {
    padding: 8px;
    font-size: 13px;
    cursor: move;
    margin-bottom: 10px;
  }

  .title {
    padding: 15px 10px;
    border-bottom: 1px solid #dcdfe6;
  }

  .disabled-tag {
    cursor: not-allowed;
    pointer-events: none;
    border: none;
    color: #c3c5ca;
  }

  :deep(.ant-layout-sider) {
    background: #fff;
    border-right: 1px solid #dcdfe6;
  }

  :deep(.ant-collapse-header) {
    word-break: break-all;
  }
</style>
